/* Create server-side or client-side for Live Room. */
'use strict';
const assert = require('assert');
const dgram = require('dgram');
const readline = require('readline');
// const fs = require('fs');

const TrackerConfig = require('../config/TrackerConfig');

function systemNotice(mes) {
  process.stdout.write(`[__NOTICE__]> ${mes}\r\n`);
}

function talkUI(mes, isRemote) {
  let prefix = isRemote ? '[__REMOTE__]> ' : '[__SEND__]> ';
  process.stdout.write(`${prefix}${mes}\r\n`);
}

class Client {
  /**
   * @param {string} port
   * @param {string} token
   */
  constructor(port, token) {

    // this.wait = new dgram.createSocket('udp4');
    this.socket = new dgram.createSocket('udp4');

    this.localUrl = {
      hostname: '0.0.0.0',
      port: port
    };

    // initialize the tracker server url
    this.remoteUrl = {
      ip: TrackerConfig.trackerHostname,
      port: TrackerConfig.trackerPort
    };

    this.token = token;

    /**
     * 0 : WAITING
     * 1 : CONNECTING
     */
    this.state = 0;

    this._start();
  }

  _start() {
    this.socket.on('listening', () => {
      systemNotice(`Listen at ${this.localUrl.hostname}:${this.localUrl.port}`);
      systemNotice(`Send token to ${this.remoteUrl.ip}:${this.remoteUrl.port}`);
    });

    this.socket.on('message', (mes, rinfo) => {
      if (this.state === 0) {
        
        if (mes.toString().match(/{"ip":"\d+\.\d+\.\d+\.\d+","port":\d+}/)) {
          
          mes = mes.toString().match(/{"ip":"\d+\.\d+\.\d+\.\d+","port":\d+}/)[0];
          this.remoteUrl = JSON.parse(mes);
          this.state = 1;
          systemNotice(`${mes} connected!`);
          
          this._talk();
          
        } else {
          systemNotice('Please wait...');
        }

      }
      else if (this.state === 1) {
        talkUI(mes.toString(), 1, rinfo.port);
      }
    });

    this.socket.bind(this.localUrl.port, this.localUrl.hostname);

    this._send();
  }

  _send() {
    this.socket.send(`${this.token}`, this.remoteUrl.port, this.remoteUrl.ip);
  }

  _talk() {
    if (this.state === 1) {
      systemNotice('Talking enabled!');
      this._readData();
    }
  }

  _readData() {
    process.stdin.on('data', (chunk) => {
      this.socket.send(`[${this.localUrl.hostname}:${this.localUrl.port}]> ${chunk}`, this.remoteUrl.port, this.remoteUrl.ip);
      talkUI(chunk, 0);
    });
  }
}

module.exports = Client;
